package com.auxgroup.smarthome.service;

import com.auxgroup.smarthome.basebean.MenuTypeEnum;
import com.auxgroup.smarthome.dto.RoleDto;
import com.auxgroup.smarthome.entity.MenuEntity;
import com.auxgroup.smarthome.entity.RoleEntity;
import com.auxgroup.smarthome.entity.RoleTag;
import com.auxgroup.smarthome.entity.UserEntity;
import com.auxgroup.smarthome.filter.PermissionSecurityUserService;
import com.auxgroup.smarthome.repo.MenuRepo;
import com.auxgroup.smarthome.repo.RoleRepo;
import com.auxgroup.smarthome.repo.UserRepo;
import com.auxgroup.smarthome.session.SessionRole;
import com.auxgroup.smarthome.syscode.Syscode;
import com.auxgroup.smarthome.web.ApiResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by kevinchen on 2016/12/27.
 */
@Service
public class RoleService{

    @Autowired
    private RoleRepo roleRepo;
    @Autowired
    private UserRepo userRepo;
    @Autowired
    private UserService userService;
    @Autowired
    private UserRepo userRepository;
    @Autowired
    private MenuRepo menuRepo;
    @Autowired
    private PermissionSecurityUserService permissionSecurityUserService;


    public ApiResponse deleteRoleById(String id) {
        RoleEntity roleEntity = roleRepo.findOne(id);
        if(null == roleEntity) {
            return ApiResponse.prompt(Syscode.ROLE_NOT_EXISTS);
        }
        UserEntity userEntity = userRepo.findByRole(roleEntity);
        if(userEntity != null) {
            return ApiResponse.prompt(Syscode.ROLE_TIED_ACCOUNT);
        }
        if(roleEntity.getRoleTag() == RoleTag.SUPPERROLE) {
            return ApiResponse.prompt("-10000", "系统创建角色，不能删除");
        }
        // 删除关联关系
        roleEntity.setMenus(null);
        roleRepo.save(roleEntity);
        // 删除角色
        roleRepo.delete(roleEntity);
        return ApiResponse.ok();
    }


    public boolean isExistRoleName(String roleName){
        RoleEntity roleEntity = roleRepo.findByRoleName(roleName);
        return roleEntity!=null ? true : false;
    }

    public boolean isExistRoleName(String rid,String roleName){
        RoleEntity roleEntity = roleRepo.findByRoleName(roleName);
        return roleEntity!=null && roleEntity.getId().compareTo(rid) !=0 ? true : false;
    }

    public boolean isExistRole(String roleId){
        RoleEntity roleEntity = roleRepo.findByIdAndDisableFalse(roleId);
        return roleEntity!=null;
    }

    public ApiResponse isExistRName(String roleName){
        boolean isExist = isExistRoleName(roleName);
        if (isExist){
            return ApiResponse.prompt(Syscode.ROLE_EXISTS);
        }
        return ApiResponse.prompt(Syscode.ROLE_NOT_EXISTS);
    }


    public ApiResponse createRole(RoleDto roleDto){
        boolean isExist = isExistRoleName(roleDto.getRoleName());
        if (isExist){
            return ApiResponse.prompt(Syscode.ROLE_EXISTS);
        }
        Set<MenuEntity> menuEntities = buildMenusByNodes(roleDto.getMenuIds());
        RoleEntity roleEntity = roleDto.createRoleEntity(new RoleEntity(), menuEntities);
        roleRepo.save(roleEntity);
        return ApiResponse.ok(roleEntity.getId());
    }


    public ApiResponse updateRole(String id, RoleDto roleDto){
        if (isExistRoleName(id,roleDto.getRoleName())){
            return ApiResponse.prompt(Syscode.ROLE_EXISTS);
        }
        RoleEntity oldRole = roleRepo.findOne(id);
        Set<MenuEntity> menuEntities = buildMenusByNodes(roleDto.getMenuIds());
        roleRepo.save(roleDto.createRoleEntity(oldRole, menuEntities));
        return ApiResponse.prompt(Syscode.SC_OK);
    }

    /**
     * 获取关联当前角色的所有权限实体
     * @param menuIds
     * @return
     */
    private Set<MenuEntity> buildMenusByNodes(List<String> menuIds){
        if (menuIds == null || menuIds.isEmpty())return null;
        List<MenuEntity> allMenusEntityList = userService.getAllMenusEntity();
        Set<MenuEntity> updateMenu = allMenusEntityList.stream().filter(m-> menuIds.contains(m.getId())).collect(Collectors.toSet());
        return updateMenu;
//        return getAllMenus(allMenusEntityList,menuIds);
    }

    /**
     * 过滤掉没有的视图模块
     * @param allMenusEntityList
     * @param menuIds
     * @return
     */
    private Set<MenuEntity> getAllMenus(List<MenuEntity> allMenusEntityList,List<String> menuIds){
        if (allMenusEntityList == null || allMenusEntityList.isEmpty()) return null;
        for(Iterator<MenuEntity> iterator = allMenusEntityList.iterator();iterator.hasNext();){
            MenuEntity next = iterator.next();
            if (next.getMenuType().equals(MenuTypeEnum.BUTTON)){
                continue;
            }
            boolean flag = false;
            for(Iterator<String> iter = menuIds.iterator();iter.hasNext();){
                String menuId = iter.next();
                if (next.getId().compareTo(menuId)==0){
                    flag = true;
                    break;
                }
            }
            if (!flag){
                iterator.remove();
            }

        }
        return new HashSet<>(allMenusEntityList);
    }

    /**
     * 根据关键词获取角色
     * modify by lixiaoxiao 2017/9/9
     * @param keyword
     * @return
     */

    public List<SessionRole> getAllRole(String keyword){
        String id = permissionSecurityUserService.getSubjectFromAccessToken();
        UserEntity curEntity = userRepository.findOne(id);
        List<RoleEntity> roleEntities = roleRepo.findAll(getWhereClause(keyword), new Sort(Sort.Direction.ASC, "createdAt"));
        List<SessionRole> roleVos = new ArrayList<SessionRole>();
        for(Iterator<RoleEntity> iterator = roleEntities.iterator();iterator.hasNext();){
            RoleEntity roleEntity = iterator.next();
            if(curEntity.getRole().getRoleTag() != RoleTag.SUPPERROLE) { // 普通管理员，过滤掉超级管理员
                if(roleEntity.getRoleTag() == RoleTag.SUPPERROLE)  continue;
            }
            roleVos.add(roleEntity.createSessionRole());
        }
        return roleVos;
    }

    public SessionRole getRolebyId(String roleId){
        RoleEntity roleEntity = roleRepo.findOne(roleId);
        return roleEntity.createSessionRole();
    }

    /**
     * 配置动态查询条件
     *
     * @return
     */
    public Specification<RoleEntity> getWhereClause(String keyword) {
        return new Specification<RoleEntity>() {
            @Override
            public Predicate toPredicate(Root<RoleEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank(keyword)) {
                    String inKeyword = "%"+keyword + "%";
                    Predicate predicate = cb.or(cb.like(root.get("roleName").as(String.class), inKeyword),
                            cb.like(root.get("roleDescription").as(String.class), inKeyword));
                    list.add(predicate);
                }
                return cb.and(list.toArray(new Predicate[list.size()]));
            }
        };
    }
}
